<?php

namespace SunAdmin\Service\FileSystem;

use SunAdmin\Model\AttachmentModel;
use think\file\UploadedFile;
use SunAdmin\Common\Utils;

class Upload extends FilesystemBase
{
    public int $uploadMaxSize = 0;
    public array $allowedFileTypes = [];
    protected string $uploaderType = '';
    protected int $uploaderUid = 0;
    protected ?UploadedFile $file = null;

    public function __construct(?string $diskName = null)
    {
        parent::__construct($diskName);
        $config = self::initConfig();
        $this->uploadMaxSize = $config['uploadMaxSize'];
        $this->allowedFileTypes = $config['allowedFileTypes'];
    }

    /**
     * 初始化配置
     */
    public static function initConfig()
    {
        $uploadMaxSize = config('swoole.http.options.package_max_length') ?? 10 * 1024 * 1024;
        $allowedFileTypes = [
            'image' => [
                'name' => "图片",
                'ext' => ['jpg', 'jpeg', 'png', 'gif', 'heic'],
                'mime' => ['image/jpeg', 'image/png', 'image/gif', 'image/heic', 'image/heif']
            ],
            'audio' => [
                'name' => "音频",
                'ext' => ['wav', 'mp3', 'm4a', 'aac'],
                'mime' => ['audio/wav', 'audio/x-wav', 'audio/mpeg', 'audio/mp3', 'video/webm', 'audio/x-m4a', 'audio/aac']
            ],
            'video' => [
                'name' => "视频",
                'ext' => ['mp4', 'mov'],
                'mime' => ['video/mp4', 'video/quicktime']
            ],
        ];
        return compact('uploadMaxSize','allowedFileTypes');
    }

    /**
     * 设置上传文件
     */
    public function setFile(UploadedFile $file): self
    {
        $this->file = $file;
        return $this;
    }

    /**
     * 设置上传者信息
     */
    public function setUploader(string $type, int $uid): self
    {
        $this->uploaderType = $type;
        $this->uploaderUid = $uid;
        return $this;
    }

    /**
     * 验证参数
     */
    protected function validate(): void
    {
        if (!$this->file) {
            throw new \Exception("缺少上传文件数据");
        }
        
        if (empty($this->uploaderType) || !in_array($this->uploaderType, ['admin', 'client'])) {
            throw new \Exception("上传者类型不正确");
        }
        
        if (empty($this->uploaderUid)) {
            throw new \Exception("上传者ID不能为空");
        }
    }

    /**
     * 验证文件
     */
    protected function validateFile(): void
    {
        $allowedExts = [];
        $allowedMimes = [];
        
        foreach ($this->allowedFileTypes as $category) {
            $allowedExts = array_merge($allowedExts, $category['ext']);
            $allowedMimes = array_merge($allowedMimes, $category['mime']);
        }
        
        $fileExt = implode(',', array_unique($allowedExts));
        $fileMime = implode(',', array_map('trim', array_unique($allowedMimes)));
        
        validate([
            'file' => "fileSize:{$this->uploadMaxSize}|fileExt:{$fileExt}|fileMime:{$fileMime}"
        ])->check([
            'file' => $this->file
        ]);
    }

    /**
     * 获取文件类型
     */
    protected function getFileType(string $ext): string
    {
        foreach ($this->allowedFileTypes as $type => $typeInfo) {
            if (in_array(strtolower($ext), array_map('strtolower', $typeInfo['ext']))) {
                return $type;
            }
        }
        return 'unknown';
    }

    /**
     * 执行上传
     */
    public function upload(string $path = 'sunAdmin'): array
    {
        try {
            $this->validate();
            $this->validateFile();
            
            // 上传文件
            $filePath = $this->filesystem->putFile($path, $this->file);
            $fileUrl = $this->filesystem->url($filePath);
            $fileExtension = $this->file->getOriginalExtension();
            
            // 保存记录
            $attachment = AttachmentModel::create([
                'name' => $this->file->getOriginalName(),
                'mime' => $this->file->getOriginalMime(),
                'size' => $this->file->getSize(),
                'ext' => $fileExtension,
                'disk' => $this->currentDisk,
                'path' => $filePath,
                'url' => $fileUrl,
                'add_time' => Utils::timeToStr(),
                'uploader_type' => $this->uploaderType,
                'uid' => $this->uploaderUid,
                'type' => $this->getFileType($fileExtension),
            ]);
            
            return [
                'status' => true,
                'data' => [
                    'id' => $attachment->id,
                    'path' => $filePath,
                    'url' => $fileUrl,
                    'disk' => $this->currentDisk
                ],
                'message' => "上传成功"
            ];
        } catch (\Exception $e) {
            \think\facade\Log::error('上传失败: ' . $e->getMessage());
            return [
                'status' => false,
                'message' => '上传失败: ' . $e->getMessage(),
                'data' => []
            ];
        }
    }
} 